// 什么是数组
//数组本质上就是让我们能 "批量" 创建相同类型的变量
// 也可以说是存储一组相同数据类型的数据的集合
//举个例子，我现在要创建一个整形数组
// int[] array
// int[] 就是相当于是一个类型（整形数组类型），
// 而 array 就相当于 该类型的变量
// 总得来说 我创建一个一个变量，它的类型是整形数组类型

// 再来看看这个 int a =10; a是变量，类型是int，且只能存储一个值。
// 而 int[] array，array是变量，类型是int[]，它能存储一组相同类型的数据（能存储类型相同的数据，个数不限，取决你想放多少个类型相同的数据）
// 例： int[] array ={1,2,3,4,5,6}
//注意事项: 在 Java 中, 数组中包含的变量必须是 相同类型

// 创建数组

//// 静态初始化
//        数据类型[] 数组名称 = { 初始化数据 };

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array ={1,2,3,4,5,6};
//    //数据类型[]+数组名称 = { 初始化数据 }; 如果后面已将数组初始化元素值了，其中[]里不能加任何数字，这是Java创建数组时，静态初始化的一个特点.
//
//    }
//}

// 既然创造出数组，就必然有它存在的价值，那么数组的好处是什么？
//如果我们没有数据的支持，我们想要定义 6 个整形会变得巨繁琐，反正我学了数组，像例子这种呆头呆脑的写就没用过了。
//例
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int a = 1;
//        int b = 2;
//        int c = 3;
//        int d = 4;
//        int e = 5;
//        int f = 6;
//    }
//}

//而且对数组有一定了解的人，都知道数组的每个元素都有一个下标（从0开始），方便去寻找寻找元素
// 而且是所有元素都存储在一块连续的空间上，所以从内存上看，所有元素都是紧邻
// 图1

//注意事项: 静态初始化的时候, 数组元素个数和初始化数据的格式是一致的（依据初始化元素的数量，来决定数组元素的个数）

// 再来看看创建数组的第二种方法： 动态初始化
//基本语法
//数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 };
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = new int[]{1,2,3,4,5,6};//其表达意思与作用与第一种方法相同
//          // 两个[]中，都不能有数字的存在
//
//        // new 是java中的一个关键字，其作用是实例化一个对象
//        // 意味着 在Java 数组其实是一个对象。对象具体是什么，后面再降
//        // （注意，并不是前面有new，数组才是一个对象，而是数组本来是就是一个对象）
//        //先这么认为，数组就是一款网页游戏，游戏没打开之前，它只是一个图标，而new的作用就是加载这游戏成为实体，就是运行起来。
//    }
//}



// 第三种创建数组的方法
// 基本语法：
// 类型[] 数组名 = new 类型[元素个数]
// 就是第二种方法中，删除了初始化数据，前者的[]中是不能有数字的存在，后者的[]可以有具体的数字来表示数组元素的个数

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = new int[6];
//        // 该写法表达的意思是 现在有一个数组，长度为6，注意数组的元素，并没有对其初始化，在Java中，默认6个元素都是0
//        // 等价于 int[] array={0,0,0,0,0,0}，
//

//    }
//}


//一套讲解下来，你会发现在Java中 是这么来表达一个数组：int[] array
//   其实数组也可以写成
//        int arr[] = {1, 2, 3};
//        和 C 语言一样. 但是我们还是更推荐写成 int[] arr 的形式. int和 [] 是一个整体.
// 但是不能像C语言一样这样写 int array[10] = {0};
// 我们前面也说了，在创建一个数组时，[]里是不能有具体数字的存在，除了第三种方法，其它的，一律不行。


//数组的使用
// 代码实例1（获取数组的长度）
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        // 注意在Java是没有sizeof这种东西的，那么有人可能会问，在数组元素个数未知的情况下，我们该如何获得数组元素个数？
//        //  方法 ： 数组名.length   这样写Java就会自动获取数组的长度（元素个数）。
//        System.out.println(array.length);
//    }// 图2
//}

// 代码实例2 读取数组中某个元素
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        // 下标从0开始，4的下标就是 3
//        // 访问方法: 数组名[下标]
//        System.out.println(array[3]);
//    }// 图 3
//}

//代码实例3（数组越界问题）

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        // 下标从0开始，也就是正数下标，不存在所谓的负数下标
//        System.out.println(array[-1]);// 我们将访问元素的下标写成负数，让我们来看看效果如何。
//    }// 图 4
//}

// 还有一种情况：元素只有 5 个，下标最高为4，你却要访问第6个元素，也就是下标为 5 的元素
//代码如下：
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        System.out.println(array[5]);// 现在我们将访问元素的下标写成5，让我们来看看效果如何。
//    }// 图 5
//}

// 代码实例4（改变数组某元素的值）
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        // 改变 元素3 的值，也就是改变数组中下标为2的元素值
//        // 方法 数组名[下标] = 新值;
//        array[2]=8;
//        System.out.println(array[2]);// 让我们来看看效果如何。
//    }// 图 6
//}

//注意事项
//        1. 使用 arr.length 能够获取到数组的长度.    . 这个操作为成员访问操作符. 后面在面向对象中会经常用到.
//        2. 使用 [ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数
//        3. 使用 [ ] 操作既能读取数据, 也能修改数据.
//        4. 下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常


// 遍历数组
// 代码实例1（for循环 - 遍历打印数组元素）
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        for (int i = 0; i < array.length; i++) {
//            System.out.print(array[i]+" ");
//            // println 是因为它自带换行，输出结果是竖着的，不好看。
//            // 所以我使用的是 print 打印不换行
//        }//图 7
//    }
//}


// 代码实例2（增加for循环 - foreach）图 8
// for(定义一个与数组元素类型相同的变量:数组名)
// 什么意思呢？
// foreach(增加for循环)， 数组名部分，表示的意思 遍历访问数组的元素
// 将访问的元素赋给 冒号前面 定义的 与数组元素类型相同的变量
// 我们只需要 将该变量每次得到的元素值，打印
// 就能做到不依靠元素下标，遍历打印数组所有元素
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        for (int x:array) {
//            System.out.print(x+" ");
//        }
//    }//图9
//}


// 那么 for 和 foreach 两者有什么区别？
// 最大的区别在于，for是可以拿到元素下标，而foreach拿不到元素下标
// for循环用到的地方很多，但是foreach呢？
// 当我们只需要元素的值时，就是使用foreach，
// 当我们还需要元素的下标时，就用for。
//for-each 是 for 循环的另外一种使用方式. 能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错


// 代码实例3（借助Java的操作数组的工具类 Arrays 图10）
// toString 将当前的数组元素，转换成字符串形式,并将其返回（也可以说 将参数的数组，以字符串形式进行输出）
//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        String str = Arrays.toString(array);// 创建一个字符串变量来接收它的返回值
//        System.out.println(str);// 图 11
//        // 因为 Arrays.toString 是有返回值的，所以可以直接输出
//         System.out.println(Arrays.toString(array));//图12
//    }
//}



// 数组作为方法的参数

// 首先我们需要搞懂几样东西
// 看代码
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array ={1,2,3,4,5};
//        int a = 10;
//
//    }
//}
// array  和  a  都是局部变量,在栈上开辟空间
// 那么问题来了，a的空间里存的是 10
// 而数组后面的一大坨数据，放在哪里？
// 和 10 一样放在栈上？
// 然而并不是，还记得前面说到 数组是一个对象吗？
// 对象是存放在 堆上的

// 在这里我们就需要介绍一些东西，图13


// 引用很像指针，最大的区别就是没有解引用，因为在Java没有传址的概念的，其他功能类似，但时两个东西，不是同一个东西，不能混淆在一起。
// 有个问题就诞生了，指针有空指针，那引用有空引用吗？
// 答案是有的，只不过跟C语言不同，C是大写NULL,Java是小写null
// 但是请注意，举这个例子只是为了让你理解引用是一个什么东西，顺便区别两者。
// C的东西只是辅助你理解Java，尽量学Java的时候，抛开C，两者（引用和指针）有很多不同地方。
// 代码实例
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] array1 = null;
//        //当一个引用被赋予null，就代表这该引用不指向任何对象
//        // 既然该引用不指向任何对象，那么我这样写代码会怎么样？
//        System.out.println(array1.length);
//        // 求一个空引用所指向的对象的长度，但是空引用不会指向任何一个对象的
//        // 何来的长度？那么代码运行的效果如何？
//        // 图14，由图可知该写法是错误的，另外引用被指为null，堆上是不会分配内存给它的
//        // 意思是你都不创建任何对象，你还想拿我空间，疯了？
//
//        System.out.println(array1[0]);
//        // 这个写法毫无疑问也是错的，没对象，你怎么访问对象里的东西？
//        // 来看看图 15
//    }
//}


// 现在我们来尝试用方法来遍历打印数组

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        print(array);
//    }
//    public static void print(int[] array){
//        for (int x:array) {
//            System.out.print(x+" ");
//        }
//        System.out.println();// 换行
//        for (int i = 0; i < array.length; i++) {
//            System.out.print(array[i]+" ");
//        }
//    }// 效果见图16
//}//让我们通过 图17 来说明
//举个例子，你玩游戏DNF，有仓库对吧，你会设密码对吧？要不然被盗号，就算找回来，里面的东西也不见了。
// 只要别人知道你的密码，他不就可以拿里面的东西了吗？
// 按引用传递，就相当于你找朋友刷东西，把密码告诉他，这样他才能打开你的仓库，在里面拿或者取 装备和材料。




// 实践题
// 下面两题先思考答案，再去看结果附图，这样你们才能对引用的理解进一步加深
//import java.util.Arrays;
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        func1(array);
//        System.out.println(Arrays.toString(array));// 图 18
//
//    }
//    public static void func1(int[] array){
//        array = new int[]{11,2,13,4,51};
//    }
//
//}

//import java.util.Arrays;
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        func2(array);
//        System.out.println(Arrays.toString(array));
//    }
//    public static void func2(int[] array){
//        array[0] = 99;
//    }
//}//图19

//上程序的两个array等价于下方程序 array 和 array1

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] array2 = array;
//     这代表  array2 这个引用 指向 引用array指向 的对象
//    }
//
//}

// 图解（图20）


// 还有一个问题值得讨论
// 一个引用 是否 能同时 指向 多个对象？
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array1 = new int[]{1,2,3,4,5};
//        array1 = new int[10];
//        array1 = new int[2];
//        array1 = new int[4];
//    }
//}
//答案是不能，如果前面认真看了，就该知道此时的array1，存储的地址，已经被改变，现在存的是 new int[4] 的这个对象的地址
// 而不是说，存几个对象的地址。
// 结论就是 一个引用只能指向一个对象（一个引用只能保存一个对象的地址）


// 写了这么多，有没有发现我们写的引用，都是在栈上
// 那么 引用 就一定在栈上吗？
// 答案是不一定的，因为一个变量在不在栈上，是你变量的性质决定的
// 如果你的引用是一个局部变量，那就一定在栈上
// 实例成员变量那就不一定了。（先告诉你们有这个概念，等后面讲到成员变量时，再说）
//总结
//局部变量和引用保存在栈上, new 出的对象保存在堆上.
//        堆的空间非常大, 栈的空间比较小.
//        堆是整个 JVM 共享一个, 而栈每个线程具有一份(一个 Java 程序中可能存在多个栈）



// 这时候，我们来讲讲前面文章留下来的问题
// 使用方法，来交换两个变量的值
// 因为Java中是取不到栈上变量的地址的，也就意味不能传址，所以无法实现
// 但是今天我们学了数组，我们用数组的方式来解决问题
//import java.util.Arrays;
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        //int a = 10;
//        //int b = 20;
//        // 我们将其放在一个数组里，进行交换
//        int[] array = {10,20};
//        swap(array);
//        System.out.println(Arrays.toString(array));
//    }
//    public static void swap(int[] array){
//        int tmp = array[0];
//        array[0] = array[1];
//        array[1] = tmp;
//    }
//}// 图21，这只是一种取巧的方式来进行交换，等到我讲到类和对象的那个时候，会再讲几种方法



// 数组作为方法的返回值
//代码示例: 写一个方法, 将数组中的每个元素都 * 2
//先来写没有返回值的（将原来的数组元素都扩大2倍）
//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        func(array);
//        System.out.println(Arrays.toString(array));
//    }
//    public static void func(int[] array){
//        for (int i = 0; i < array.length; i++) {
//            array[i]=2*array[i];
//        }
//    }//图22
//}// 图解（图23）


// 如果我不想在原来的数组上扩大2倍呢？（保护原来的数组不被破坏）

// 代码入下

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//         int[] ret = func(array);
//        System.out.println(Arrays.toString(ret));
//        System.out.println(Arrays.toString(array));
//    }
//    public static int[] func(int[] array){
//         int[] ret = new int[array.length];
//        for (int i = 0; i < array.length; i++) {
//            ret[i]=2*array[i];
//        }
//        return ret;
//    }//图24
//}// 图解（图25）
//这样的话就不会破坏原有数组了.
//另外由于数组是引用类型, 返回的时候只是将这个数组的首地址返回给函数调用者, 没有拷贝数组内容, 从而比较高效.
//有的人可能会说，方法调用完的时候，不是会销毁栈上的空间，我们这样将地址带回来，不会存在一些吗？
// 请注意 new 的对象，都是存在堆上的，而不是栈上。这里的返回是将堆上对象的地址（注意返回类型int[]），而不是局部变量ret，所以不会出现问题


//数组练习
//模拟实现 toString 函数
// toString 将当前的数组元素，转换成字符串形式,并将其返回（也可以说 将参数的数组，以字符串形式进行输出） 图12
// 代码如下

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        String str = myToString(array);
//        System.out.println(str);
//    }
//    public static String myToString(int[] array){
//        if(array == null){
//            return "null";// 判断是否形参接收的地址，是否为空指针
//        }
//        String str = "[";
//        for (int i = 0; i < array.length; i++) {
//            str+=array[i];// 用了一开始拼接输出方式，字符串开头后面用+拼接，使其成为一个字符串
//            if(i< array.length-1){// array.length-1，因为最后一个元素不用加 ，号
//                str+=",";
//            }
//        }
//        str+="]";
//        return  str;
//    }
//}// 图26



//找数组中的最大元素
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {12,8,1,2,10};
//        System.out.println(maxNum(array));
//    }
//    public static int maxNum(int[] array){
//        if(array==null){
//            return -1;// 假设 -1 意味着array存储的是空指针
//        }
//        if(0 == array.length){
//            return -2;// 假设 -2 意味着 array 没有元素（int[] array = {}）
//            // 故 数组长度为0（元素个数为0）.
//        }
//        int max = array[0];
//        for (int i = 1; i < array.length; i++) {
//            if(max<array[i]){
//                max = array[i];
//            }
//        }
//        return max;
//    }// 图 27
//}

//查找数组中指定元素(顺序查找),返回它的下标
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,23,213,67,123};
//        System.out.println(find(array,23));
//    }
//    public static int find(int[] array,int y){
//
//        for (int i = 0; i < array.length; i++) {
//            if (array[i] == y){
//               return i;
//            }
//        }
//        return -1;// 表示没找到，因为数组的下标不可能存在负数
//    }
//}

//查找数组中指定元素(二分查找),返回其下标
//        针对有序数组, 可以使用更高效的二分查找

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        System.out.println(find(array,4));
//    }
//    public static int find(int[] array,int y){
//        int right = array.length-1;// 右下标
//        int left = 0;// 左下标
//        int mid = 0;
//        while(right>=left){
//            mid=(right+left)/2;
//            if(array[mid]>y){
//                right--;
//            }
//            else if(array[mid]<y){
//                left++;
//            }else{
//                return mid;
//            }
//        }
//        return -1;//表示没找到
//    }
//}// 图28
// 图释（ 图29）


//其实在Java中有一个工具，就是二分查找，意味这我们没必要像上面一样去写一个二分查找的方法
// 写法 Arrays.binarySearch(数组名，想查找的元素)

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        System.out.println(Arrays.binarySearch(array,2));// 图30
//        // 如果找一个不存在的数呢？
//        System.out.println(Arrays.binarySearch(array,6));// 图 31
//        // 有人会好奇，为什么是-6？
//        // 左键点击 binarySearch，ctrl + 左键点击
//        // 再点击 binarySearch，ctrl + 左键点击
//        // 你会看到 图 32
//        // -(low+1),意思是最后low的位置下标+1，取负
//        // 因为我们要找的数，比有序数组里所有元素都要大，所以最后low的位置应该最后一个元素的位置
//        // 也就是下标为 5 的位置，对其加一取负，所以输出的值是-6
//        // 另外注意，下标是没有负数的，别以为这-6 是一个元素的下标，不是的啊。
//        // 只是告诉你找不到。
//        // 下标不可能为负，你给我个负数，不是找不到是什么
//    }
//}


// 二分查找对于有序数列的效率是非常高的，你想想取一个中间下标的值
// 不管你要找的数，是大于或者小于这个值，都意味着有一边的数据直接pass。
// 图33



 // 检查数组的有序性（升序：从左往右，从小到大）
//public class TheDefinitionAndUseOfArrays {
//     public static void main(String[] args) {
//         int[] array = {1,2,3,10,5,6};
//         System.out.println(isSorted(array));
//     }
//     public static  boolean isSorted(int[] array){
//         for (int i = 0; i < array.length-1; i++) {
////    注意 array.length-1，为什么减一呢？因为你想想看，假设有6个元素（array.length == 6）
////   但是下标最大为 5 == array.length-1，因为有小于号，所以这个减一，可以被省略，那为什么还要减一？
////   注意我们的if条件（array[i]>array[i+1]），当循环元素到下标为5的元素（最后一个元素），就会有问题了
//// array[i+1] == array[6] == 第七个元素，第七个元素有没有？没有。那我们访问的话会产生数组越界访问错误
//// 图35
//             if(array[i]>array[i+1]){// 左边的元素比右边的元素大，那么就不满足升序，称为乱序
//                 return false;// 乱序
//             }
//         }
//         return true;// 有序
//     }
//}// 图34



// 数组排序（冒泡排序）
// 升序

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {9,5,2,7};// 我们假设一个整形数组
//        bubbleSort(array);
//        // 调用我们的自定义的冒泡的方法,把我们的数组名（引用）扔过去，按引用传递
//        System.out.println(Arrays.toString(array));// 偷个油，不用循环打印，将其转换成字符串输出
//    }
//    public static void bubbleSort(int[] array){// 创建一个 数组变量，来接收传参
//         // 理一下思绪，首先假设我定义一个 i 来表示元素下标，通过引用（数组名） 和 [] 来访问下标所对应的函数。
//        //既然要排升序，肯定要比较大小，不可能自己跟自己比吧？要跟它后面的元素比，比它大，相互交换位置，反则什么都不做（升序）。
//        // 但是不可能只比一次，我这里有四个元素，至少要比3次，才能完成把最大的数放在最后。
//        // 有的人可能会说，不是有4个元素吗？不应该是4次，记住我们2个一比，每次都是前面比后面，
//        // 到了倒数第二个元素，它是最后的元素相比较，比较完了，那么最后一个元素已经最大的了，还有比较的意义吗？没有！
//        //而且这是，一趟，还要比较3趟。我们第一趟比较只是把最大的数，放到了最后，其它三个数，还不知是否是升序
//        // 图 36
//
//        // 现在我们正式开始
//        for (int i = 0; i < array.length; i++) {// 有4个元素，需要比 3 趟
//            // 根据 36 最后的结论，表示有可能，在未来完成某一趟比较之后，后面的数值已经有序，那我们没有比较的必要
//            // 所以 我们在这里定义一个 flag = 1，再在 交换程序中 写一个flag=0;
//            // 什么意思呢？ 就是你只要交换了两元素的位置，说明这一趟，数组肯定不是有序的，你都交换了，还有序？
//            // 如果 这一趟下来flag还是等于1，我们结束整个排序，为什么？因为根据图36来看，冒泡排序的比较模式 是交换式比较，
//            // 1 和 2 一比，比完； 2 和 3一比，也就是如果flag等于1，说明后面没有发生交换
//            // 后面的每一位都比自身前一位都要大(比前面的位，早在之前就给你换了)
//            //  说明升序排列完成
//            int flag =1;// 假设这一趟是有序的
//
//            // 每一趟的比较过程
//            for (int j = 0; j < array.length-1-i; j++) {// 减一是为了防止越界，这个应该都懂
//                // 至于减 i，想想看，我们每一趟比较，把最大的数往后排，小的数往前挪，作为下一次标胶的起点
//                // 再加上这一趟比下来，可以说一个数跟其他都比较了，只有全比较了，我们才能知道最大数究竟是谁？
//                // 得出了最大数，放在最后，那还有比较的必要，再去比，就是疯了。（都打过一架了，还输了，你还找别人去单挑，不是疯了，就是zz）
//                // 所以每比完一趟，我们比较次数就减一，
//                // 第一次，i==0，是因为倒数2个大值，还需要比较，你再减一个1，还比什么。搞黑手？还没比，就把最后的一位数，放在最后一位
//                // 万一倒数第二位，比最后的数，要大呢？，这不是搞黑幕，是搞什么？嗯？
//                if(array[j]>array[j+1]){
//                    // 升序，前者比后者小，只要前者比后者大，就意味着需要交换位置
//                    int tmp = array[j];
//                    array[j] = array[j+1];
//                    array[j+1]=tmp;
//                    // 假设
//                    //  2 1
//                    // tmp = 2 == array[0] ;  array[0] = array[1] == 1,此时array[0]已经被改变
//                    // array [1] = tmp ==2;
//                    // 即 数组元素顺序 为 1，2
//
//                    flag = 0;// 都交换了，那么肯定是不是有序的
//                }
//            }
//            if(1== flag){
//                break;//如果flag等于1，说明后面的每一位都比自身前一位都要大,那就说明没有比较的意义，同时意味着排序完成，跳出循环。
//            }
//        }
//
//        //来看看看结果 图 37
//    }
//}




// 经过上面的讲解，至少你有一定的了解
// 很遗憾,我想告诉你，我们辛辛苦苦做出的冒泡排序，在Java是有函数可以做到的（并不意味我们刚才的努力都是白费，万一面试官，让你模拟实现一个冒泡排序呢？）
// 对吧？ 废话不多说，我们来看看这哥函数是什么？
//import java.util.Arrays;
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {9,5,2,7};
//        Arrays.sort(array);// 是借助Java工具Arrays.sort来完成的，图 39
//        System.out.println(Arrays.toString(array));// 图38
//    }
//}




// 我们在顺便拓展一下 Arrays 的其它功能
//import java.util.Arrays;
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = new int[10];// 此时数组默认10个元素都是0,图40
//        Arrays.fill(array,99);// fill 是 填的意思，图 42
//        System.out.println(Arrays.toString(array));// 效果见 图 41
//    }
//}

// 根据图 43，发现 Arrays。fill 的参数，还可以写两个
//import java.util.Arrays;
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = new int[10];// 此时数组默认10个元素都是0,图40
//        Arrays.fill(array,0,5,99);// 意思将下标为0的元素到下标为4的元素全部置为0
//        // 至于为什么不是下标为5，是因为 该范围是 左闭右开 [0,5) ==   0=<下标 && 下标<5
//        System.out.println(Arrays.toString(array));// 效果见 图 44
//    }
//}

//数组逆序
// 假设数组元素顺序为 1,2,3,4,5（并不一定是有序，只是为了举例方便)
// 5，4,3,2,1

//import java.util.Arrays;
//
//public  class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        echange(array);
//        System.out.println(Arrays.toString(array));// 图 45
//    }
//    public static void echange(int[] array){
//        int left =0;// 左下标
//        int right = array.length-1;// 右下标
//        while(left<right){
//            // 就是两边的数据对着换
//            // 当left 和 right 所指向的下标相遇是，也就同一个元素
//            // 循环终止
//            int tmp = array[left];
//            array[left]=array[right];
//            array[right]= tmp;
//            right--;
//            left++;
//        }
//    }
//}



// 数组数字排列
//给定一个整型数组, 将所有的偶数放在前半部分, 将所有的奇数放在数组后半部分
//例如
//        {1, 2, 3, 4}
//        调整后得到
//        {4, 2, 3, 1}

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4};
//        transform(array);
//        System.out.println(Arrays.toString(array));// 图 46
//    }
//    public static void transform(int[] array){
//        int left = 0;
//        int right = array.length-1;
//        while(left<right){
//            while(left<right && array[left]%2 == 0){
//                // 找奇数（%2 !=0），找到了，跳出循环
//                  left++;
//                  // left 是不能一直加加的，如果没有 left<right 这个限制条件，在交换完成（left和right相遇），该下标还会一直 ++。
//                 // 甚至可能会越界(全偶数)，因为（小）循环体执行完了，才会去判断（大）循环条件，
//            }
//            while(left<right && array[right]%2 != 0 ){
//                // 找偶数(%2 == 0),找到了，跳出循环
//                right--;// 这个与left同理
//            }
//            int tmp = array[left];
//            array[left] = array[right];
//            array[right] = tmp;
//        }
//    }
//}


//数组拷贝


// 拷贝方法1 循环拷贝
// 假设你要拷贝的数组 是 int[] array = {1,2,3,4,5}
// 那么我就需要 创一个相同类型,元素个数相同的 数组变量array2来接收（int[] array2 [array.length]）
// 通过 对应的下标进行复制拷贝
// 代码如下

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array={1,2,3,4,5};
//        int[] array2 = copyOf(array);// 是方法中 引用ret存储值的一份拷贝，能够访问 ret 指向的堆上的对象
//        System.out.println(Arrays.toString(array));
//        System.out.println(Arrays.toString(array2));// 图 47
//    }
//    public static int[] copyOf(int[] array){
//        int[] ret = new int[array.length];//创一个相同类型,元素个数相同的 数组变量array2来接收 array 的元素
//        for (int i = 0; i < array.length; i++) {
//            ret[i] = array[i];//通过 对应的下标进行复制拷贝
//        }
//        return  ret;// 将对象的地址转过去
//    }
//}// 图 48



// 方法2
// 利用Java提供的函数： Arrays.copyOf
// 图49

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] array2 = Arrays.copyOf(array,array.length);
//        System.out.println(Arrays.toString(array2));// 图 50
//        // 既然能规定 拷贝数量，我输入拷贝数量超过，源数组array的元素个数呢？
//        int[] array3 = Arrays.copyOf(array,array.length*2);
//        System.out.println(Arrays.toString(array3));// 图 51，由图可知类似扩容
//    }// 但是注意一点，本质是copy明白嘛？ 这扩容出来的数组，跟元素组，不是同一个数组
//    // 左键点击copyOf +Ctrl+左键）,来看看得到的图52，由图52，还可以得知 如果我们想"扩容"，输入的倍数必须整数，因为它的长度类型规定为整形
//}



//方法3
// 不知道你们注意到没？ 图52中的一个程序语句
// 图 53
// 图中所圈部分，就是我们拷贝数组的第三种方法

// 但是我们先来看第四种方法
// Arrays.copyRange()
// 图54


//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] ret = Arrays.copyOfRange(array,0,4);
//        System.out.println(Arrays.toString(ret));//图 55
//    }
//}


// 好，现在我们来看看 第三方法
// 图 53
//
//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] array2 = new int[array.length];
//        System.arraycopy(array,0,array2,0,array.length);
//        // 跟用for循环进行拷贝时一个道理，根据对应的下标进行赋值拷贝
//        System.out.println(Arrays.toString(array2));
//        // 图 56
//    }
//}
// 拓展
// 图 57
// 注意图中所圈部分，怎么进我就不再教了，忘了就往上翻。
// 我来提示你，System.arraycopy是不是没有实现过程，只是一个类似函数声明一样，放在哪里？
// 那它是怎么实现数组拷贝的呢?
// 这就跟我们所圈起来的native（本地的）有关，
// 所有被 native 所修饰的方法，方法的实现过程，都已经被 C/C++ 实现了。
// 我们是看不到运行过程的，这样写的最大好处就是 速度快，效率高



// 方法 5  数组克隆
// 基本语法：
// 数组名.clone();

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[] array = {1,2,3,4,5};
//        int[] array2 = array.clone();// 类似 副本，不是游戏副本啊！
//        // 可以理解为是一份资料的备份
//
//        System.out.println(Arrays.toString(array2));
//    }// 图58
//}


// 在 一维数组的最后我们在讲一个概念， 深拷贝 和 前拷贝
// 图 59



// 二维数组

// 二维数组的创建

// 基本语法1
// 数据类型[][] 数组名 = { 初始化数据 }

// 基本语法2
// 数据类型[][] 数组名 = new 数据类型[][]{ 初始化数据 }

//基本语法3
// 数据类型[][] 数组名 = new 数据类型[行数][列数]

// 跟一维数组几乎一样，只要初始化了数据，你的[][]里就不能有数字的存在

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        // 创建一个 2行3列的二维数组
//        int[][] array = {{1,2,3},{4,5,6}};
//        int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
//        int[][] array3 = new int[2][3];
//    }
//}


// 二维数组的打印


//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        // 创建一个 2行3列的二维数组
//        int[][] array = {{1,2,3},{4,5,6}};
//        int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
//        int[][] array3 = new int[2][3];
//        print(array);
//    }
//    public static void print(int[][] array){
//        // 按照我们以前对C的理解，二维数组的存储模式应该为图60
//        for (int i = 0; i < 2; i++) {
//            for (int j = 0; j < 3; j++) {
//                //打印一行数据
//                System.out.print(array[i][j] + " ");
//            }
//            System.out.println();// 换行
//        }
//    }
//}
// 图 61，由图的结果来看没问题
// 但是我总不能，每个二维数组都去算它有几个元素吧。
// 问题就在于怎么去获得 行 和 列
// 这里就引用C语言的一个概念，二维数组是一个特殊的一维数组
// 经过前面讲解，大家都知道数组是存储在堆上的，再加上面这句话的概念
// 让我们看看图62

// 接着我们来对上面的程序进行改良
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        // 创建一个 2行3列的二维数组
//        int[][] array = {{1,2,3},{4,5,6}};
//        int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
//        int[][] array3 = new int[2][3];
//        print(array);
//        // 这里我们在用实例证明一下
//        // array.length 是否能的得到 行数 2
//        System.out.println(array.length);
//        // array[下标].length 是否能得到 列数3
//        System.out.println(array[0].length);
//        System.out.println(array[1].length);
//    }
//    public static void print(int[][] array){
//        // 按照我们以前对C的理解，二维数组的存储模式应该为图60
//        for (int i = 0; i < array.length; i++) {
//            for (int j = 0; j < array[i].length; j++) {
//                //打印一行数据
//                System.out.print(array[i][j] + " ");
//            }
//            System.out.println();// 换行
//        }
//    }
//}// 图63



// 前面使用for循环来打印数组，这回我们foreach
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[][] array = {{1,2,3},{4,5,6}};
//        print(array);
//    }
//    public static void print(int[][] array){
//        for (int[] ret:array) {// array元素的数据类型是一个一维数组，我就需要一个相同的类型的变量来接收
//            for (int x:ret) {
//                // ret是一个一维数组的数组名，接下来就跟前面使用foreach是一样，将 引用ret 所指向的对象（数组）的元素，
//                // 读取并赋值给 与其元素类型相同的变量， 我们再将其输出。就可以了
//                System.out.print(x + " " );
//            }
//            System.out.println();//换行
//        }
//    }
//}// 图 64


// 还有一种输出二维数组的方法
// 在前面，我们使用了 Arrays.toString，将数组转换的字符串输出

// 二维数组也有对应的 方法： Arrays.deepToString(数组名)

//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[][] array = {{1,2,3},{4,5,6}};
//        System.out.println(Arrays.deepToString(array));
//    }
//}//图 65




// 接下来，我会让你们见识到一种特别的二维数组

//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[][] array = {{1,2},{1,2,3}};
//        for (int[] ret:array) {
//            for (int x:ret) {
//                System.out.print(x+" ");
//            }
//            System.out.println();// 换行
//        }
//    }
//}//图 66，见证奇迹，参考图62

// 再来举个例子
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[][] array = new int[2][];
//        // 在C语言中，二维数组，是不能省略列的，行可以省略
//        // 而Java与之相反，行不能省略，列可以（图67、68）
//        for (int i = 0; i < array.length; i++) {
//            for (int j = 0; j < array[i].length; j++) {
//                System.out.print(array[i][j] + " ");
//            }
//            System.out.println();// 换行
//        }
//    }//图 69，图 70
//}


// 哪有人可能会问，虽然写法没问题，但是程序运行会报错，那么省略列的意义在哪？
// 意义在于我们可以改，去赋予
// 这种二维数组，我们将其称为 不规则的二维数组，
//import java.util.Arrays;
//
//public class TheDefinitionAndUseOfArrays {
//    public static void main(String[] args) {
//        int[][] array = new int[2][];
//        array[0]=new int[3];// 意味着第一个数组长度为3
//        array[1]=new int[2];// 意味着第二个数组长度为2
//        System.out.println(Arrays.deepToString(array));
//    }
//}// 图71，72






